#include "Utils.h"

static const char label[] = "Utils: ";

ifstream Utils::inStream;
ofstream Utils::outStream;
ofstream Utils::logStream;

/****************************************************************
 * Constructor.
**/
Utils::Utils()
{
}
/****************************************************************
 * Destructor.
**/
Utils::~Utils()
{
}

/****************************************************************
 * General functions.
**/
/****************************************************************
 * Check for the correct number of arguments.
**/
void Utils::checkArgs(int howMany, int argc, char *argv[], string usage)
{
  if(argc != howMany + 1)
  {
    cout << label << "incorrect argument count" << endl;
    cout << label << "usage: " << argv[0] << " " << usage << endl;
    exit(1);
  }
}

/****************************************************************
 * Close an input stream.
**/
void Utils::FileClose(ifstream& inStream)
{
  cout << label << "close the input file" << endl;
  inStream.close();
  cout << label << "the input file was closed" << endl;
}

/****************************************************************
 * Close an output stream.
**/
void Utils::FileClose(ofstream& outStream)
{
  cout << label << "close the output file" << endl;
  outStream.close();
  cout << label << "the output file was closed" << endl;
}

/****************************************************************
 * Open an input stream.
**/
void Utils::InFileOpen(string fileName)
{
  cout << label << "open the input file '" << fileName << "'" << endl;
  inStream.open(fileName.c_str());
  if(inStream.fail())
  {
    cout << label << "open failed for " << fileName << endl;
    exit(0);
  }
  cout << label << "open succeeded for '" << fileName << "'" << endl;
}

/****************************************************************
 * Open a logfile stream.
**/
void Utils::LogFileOpen(string fileName)
{
  cout << label << "open the logfile '" << fileName << "'" << endl;
  logStream.open(fileName.c_str());
  if(logStream.fail())
  {
    cout << label << "open failed for " << fileName << endl;
    exit(0);
  }
  cout << label << "open succeeded for '" << fileName << "'" << endl;
}

/****************************************************************
 * Open an output stream.
**/
void Utils::OutFileOpen(string fileName)
{
  cout << label << "open the output file '" << fileName << "'" << endl;
  outStream.open(fileName.c_str());
  if(outStream.fail())
  {
    cout << label << "open failed for " << fileName << endl;
    exit(0);
  }
  cout << label << "open succeeded for '" << fileName << "'" << endl;
}

/****************************************************************
 * Call the timing function
**/
string Utils::timecall(string timestring)
{
  char s[160];
  string returnValue;
  static bool firsttime = true;
  static double usercurrent = 0.0,userone = 0.0,usertwo = 0.0;
  static double systemcurrent = 0.0,systemone = 0.0,systemtwo = 0.0;
  static double cpupctone,cpupcttwo;
  static double TIMEsystemtotal,TIMEusertotal;
  static struct rusage rusage;
  static time_t TIMEtcurrent,TIMEtone,TIMEttotal = 0.0,TIMEttwo;

  if(firsttime)
  {
    firsttime = false;
    TIMEusertotal = 0.0;
    TIMEsystemtotal = 0.0;
    TIMEtone = time(0);
    TIMEttwo = time(0);
  }

  getrusage(RUSAGE_SELF,&rusage);

  usertwo = (double) rusage.ru_utime.tv_sec;
  usertwo += (double) rusage.ru_utime.tv_usec/1000000.0;
  systemtwo = (double) rusage.ru_stime.tv_sec;
  systemtwo += (double) rusage.ru_stime.tv_usec/1000000.0;

  usercurrent = usertwo - userone;
  systemcurrent = systemtwo - systemone;

  TIMEusertotal += usercurrent;
  TIMEsystemtotal += systemcurrent;

  TIMEttwo = time(0);
  TIMEtcurrent = TIMEttwo - TIMEtone;
  TIMEttotal += TIMEtcurrent;
  if(TIMEtcurrent != 0)
  {
    cpupctone = 100.0 * ((double)usercurrent+systemcurrent) /
                           ((double)(TIMEtcurrent));
    if(cpupctone > 100.0) cpupctone = 100.0;
  }
  else
  {
    cpupctone = 0.0;
  }

  if(TIMEttotal != 0)
  {
    cpupcttwo = 100.0 * ((double)TIMEusertotal+TIMEsystemtotal) /
                           ((double)(TIMEttotal));
    if(cpupcttwo > 100.0) cpupcttwo = 100.0;
  }
  else
  {
    cpupcttwo = 0.0;
  }

  returnValue = "";
  sprintf(s,"\nTIME***********************************************************************\n");
//  cout << s;
  returnValue += static_cast<string>(s);

  sprintf(s,"TIME CPU percent  %6.2f %6.2f                    %s",
             cpupctone,cpupcttwo,ctime(&TIMEttwo));
//  cout << s;
  returnValue += static_cast<string>(s);

  sprintf(s,"TIME %-15s %10.2f u   %10.2f s\n",
                 timestring.c_str(),usercurrent,systemcurrent);
//  cout << s;
  returnValue += static_cast<string>(s);

  sprintf(s,"TIME %-15s %10.2f u_t %10.2f s_t\n",
                 timestring.c_str(),TIMEusertotal,TIMEsystemtotal);
//  cout << s;
  returnValue += static_cast<string>(s);

  sprintf(s,"TIME***********************************************************************\n");
//  cout << s;
  returnValue += static_cast<string>(s);

//  cout << "\n" << endl;
  returnValue += "\n\n";

//  cout.flush();

  userone = usertwo;
  systemone = systemtwo;
  TIMEtone = TIMEttwo;

  return returnValue;
} // string Utils::timecall(string timestring)

/****************************************************************
 * Convert a string to all lowercase.
**/
void Utils::toLower(string& to, string from)
{
  static char c[80];

  sprintf(c, "%s", from.c_str());
  for(unsigned int i = 0; i < from.length(); ++i)
  {
    if(isupper(c[i])) c[i] = tolower(c[i]);
  }
  to = (string) c;
}
